""" 复用字符处理静态方法模块"""
import logging
import os
import re

from code_metric.config import init_global_config_setting, init_output_path
from code_metric.utils import make_sure_dir_exist, get_date

CONFIG = init_global_config_setting()
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
OUTPUT_DIR = init_output_path()

BLAME_AUTHOR_EMAIL_PATTERN = re.compile(
    r'(?<=\(<).+(?=>\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [+-]\d{4}\s+\d+\))')
EMAIL_HOST_PATTERN = re.compile(r'(@| at )([\w-]+\.)+[A-Za-z]+')
AUTHOR_EMAIL_PATTERN_SHOW = re.compile(r'(?<= <).+(?=>)')
FILE_MOD_PATTERN_SHOW = re.compile(r'(\d+)\s+(\d+)\s+(.+)')


def parse_repo_info_into_dict(repo):
    name = repo['name']
    link = 'https://gitee.com/' + repo['full_name']
    desc = repo['description']
    status = repo['status']
    created_at = repo['created_at']
    return dict(仓库名称=name, 仓库链接=link, 仓库描述=desc, 仓库状态=status, 创建时间=created_at)


def parse_file_path_to_file_type(file_path):
    file_type = os.path.splitext(file_path)[-1]
    return file_type


def parse_file_path_to_underscore_name(file_path):
    return file_path.replace('\\', '_').replace('/', '_').replace('.', '_')


def parse_file_name_to_unified_path_name(repo_name, file_name):
    return repo_name + '\\' + file_name.replace('/', '\\')


def parse_owner_and_repo_name_to_repo_url(owner_name, repo_name):
    repo_url = 'https://gitee.com/' + owner_name + '/' + repo_name
    return repo_url


def parse_repo_url_to_owner_and_repo_name(repo_url):
    owner_name = find_owner_name_from_repo_url(repo_url)
    repo_name = find_repo_name_from_repo_url(repo_url)
    return owner_name, repo_name


def parse_email_to_host(email):
    if '@' not in email:
        email = re.sub(r'\s+at\s+', '@', email)
        email = re.sub(r'\s+dot\s+', '.', email)
    if '@' not in email:
        email = re.sub(r'_+at_+', '@', email)
        email = re.sub(r'_+dot_+', '.', email)
    matches = EMAIL_HOST_PATTERN.search(email)
    if matches is not None:
        return matches.group()
    if '@' in email:
        nonstandard_host = email[email.find('@'):]
        logging.warning(f'所传入的邮箱：{email}中，host信息不标准，即将返回{nonstandard_host}')
        return nonstandard_host
    logging.warning(f'没有在传入的邮箱：{email}中，找到邮箱host信息')
    return CONFIG['no_host']


def parse_git_show_info_to_add_del_file(git_show_line):
    matches = FILE_MOD_PATTERN_SHOW.search(git_show_line)
    return matches.group(1), matches.group(2), matches.group(3)


def parse_ref_location_from_ref_type(ref_type):
    if ref_type == 'Branch':
        return 'origin/'
    elif ref_type == 'Tag':
        return 'refs/tags/'
    elif ref_type == 'SHA':
        return ''
    else:
        logging.error('所传入的引用类型，不是预设的Branch/Tag/SHA，即将采用默认值Branch')
        return 'origin/'


def parse_str_without_punctuation(line, punc_list):
    for punc in punc_list:
        line = line.replace(punc, '')
    return line


def get_org_workspace_path(org_name):
    return os.path.join(OUTPUT_DIR, org_name)


def find_author_email_in_blame(line):
    matches = BLAME_AUTHOR_EMAIL_PATTERN.search(line)
    if matches is None:
        no_author_info = CONFIG['no_author']
        logging.warning(f'字符串{line}中，没有邮箱，即将返回默认字符{no_author_info}')
        return no_author_info
    return matches.group()


def find_author_email_in_show(line):
    matches = AUTHOR_EMAIL_PATTERN_SHOW.search(line)
    if matches is None:
        no_author_info = CONFIG['no_author']
        logging.warning(f'字符串{line}中，没有邮箱，即将返回默认字符{no_author_info}')
        return no_author_info
    return matches.group()


def find_owner_name_from_repo_url(repo_url):
    owner_name = ''
    prefix = 'https://gitee.com/'
    if prefix in repo_url:
        owner_name = re.search(rf'(?<={prefix})[^/]+(?=/|$)', repo_url).group()
    return owner_name


def find_repo_name_from_repo_url(repo_url):
    return re.search(r'(?<=/)[^/]+?(?=$|\.git)', repo_url).group()


def form_absolute_path_from_dir_and_file(dir_path, file_name):
    make_sure_dir_exist(dir_path)
    file_in_absolute_path = os.path.join(dir_path, file_name)
    return file_in_absolute_path


def form_abs_name_for_org_repos_info_file(org_name):
    org_workspace_dir = get_org_workspace_path(org_name)
    output_file_name = '_'.join([org_name, CONFIG['org_repos_info']]) + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(org_workspace_dir, output_file_name)


def form_abs_name_for_version_repos_info_file(org_name, version_name):
    if version_name == 'master':
        return form_abs_name_for_org_repos_info_file(org_name)
    org_workspace_dir = get_org_workspace_path(org_name)
    output_file_name = '_'.join([org_name, version_name, CONFIG['version_repos_info']]) + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(org_workspace_dir, output_file_name)


def form_abs_name_for_repo_cloc_raw_file(repo):
    org_workspace_dir = get_org_workspace_path(repo.owner_name)
    output_file_dir = os.path.join(org_workspace_dir, CONFIG['cloc_path'], repo.ref)
    output_file_name = '_'.join([get_date(), repo.owner_name, repo.ref, repo.name, 'cloc']) + '.txt'
    return form_absolute_path_from_dir_and_file(output_file_dir, output_file_name)


def form_abs_name_for_repo_cloc_excel_file(repo):
    org_workspace_dir = get_org_workspace_path(repo.owner_name)
    output_file_dir = os.path.join(org_workspace_dir, CONFIG['cloc_path'], repo.ref)
    output_file_name = '_'.join([get_date(), repo.owner_name, repo.ref, repo.name, CONFIG['code_lines_report']]) \
                       + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(output_file_dir, output_file_name)


def form_abs_name_for_repo_blame_raw_file(repo, file):
    org_workspace_dir = get_org_workspace_path(repo.owner_name)
    output_file_dir = os.path.join(org_workspace_dir, CONFIG['blame_path'], repo.ref, repo.name)
    output_file_name = '_'.join([get_date(), file.flat_name, 'blame']) + '.txt'
    return form_absolute_path_from_dir_and_file(output_file_dir, output_file_name)


def form_abs_name_for_repo_blame_excel_file(repo, file):
    org_workspace_dir = get_org_workspace_path(repo.owner_name)
    output_file_dir = os.path.join(org_workspace_dir, CONFIG['blame_path'], repo.ref, repo.name)
    output_file_name = '_'.join([get_date(), file.flat_name, CONFIG['coder_lines_report']]) \
                       + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(output_file_dir, output_file_name)


def form_abs_name_for_commit_show_raw_file(repo, commit):
    org_workspace_dir = get_org_workspace_path(repo.owner_name)
    output_file_dir = os.path.join(org_workspace_dir, CONFIG['show_path'], repo.name, repo.ref)
    output_file_name = '_'.join([get_date(), commit.id, 'show']) + '.txt'
    return form_absolute_path_from_dir_and_file(output_file_dir, output_file_name)


def form_abs_name_for_commit_show_excel_file(repo, commit):
    org_workspace_dir = get_org_workspace_path(repo.owner_name)
    output_file_dir = os.path.join(org_workspace_dir, CONFIG['show_path'], repo.name, repo.ref)
    output_file_name = '_'.join([get_date(), commit.id, CONFIG['commit_lines_report']]) \
                       + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(output_file_dir, output_file_name)


def form_abs_name_for_version_code_line_report(version):
    org_workspace_dir = get_org_workspace_path(version.owner_name)
    output_file_name = '_'.join([version.owner_name, version.name, get_date(), CONFIG['code_lines_report']]) \
                       + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(org_workspace_dir, output_file_name)


def form_abs_name_for_version_author_code_line_report(version):
    org_workspace_dir = get_org_workspace_path(version.owner_name)
    output_file_name = '_'.join([version.owner_name, version.name, get_date(), CONFIG['coder_lines_report']]) \
                       + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(org_workspace_dir, output_file_name)


def form_abs_name_for_version_group_code_line_report(version):
    org_workspace_dir = get_org_workspace_path(version.owner_name)
    output_file_name = '_'.join([version.owner_name, version.name, get_date(), CONFIG['group_lines_report']]) \
                       + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(org_workspace_dir, output_file_name)


def form_abs_name_for_repo_code_line_report(repo):
    org_workspace_dir = get_org_workspace_path(repo.owner_name)
    output_file_name = '_'.join([repo.owner_name, repo.name, repo.ref, get_date(), CONFIG['code_lines_report']]) \
                       + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(org_workspace_dir, output_file_name)


def form_abs_name_for_repo_author_line_report(repo):
    org_workspace_dir = get_org_workspace_path(repo.owner_name)
    output_file_name = '_'.join([repo.owner_name, repo.name, repo.ref, get_date(), CONFIG['coder_lines_report']]) \
                       + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(org_workspace_dir, output_file_name)


def form_abs_name_for_file_author_line_report(file):
    org_workspace_dir = get_org_workspace_path(file.repo.owner_name)
    output_file_name = '_'.join(
        [file.repo.owner_name, file.repo.name, file.repo.ref, file.flat_name, get_date(),
         CONFIG['coder_lines_report']]) + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(org_workspace_dir, output_file_name)


def form_abs_name_for_commit_code_line_report(commit):
    org_workspace_dir = get_org_workspace_path(commit.repo.owner_name)
    output_file_name = '_'.join([commit.repo.owner_name, commit.id, get_date(), CONFIG['commit_lines_report']]) \
                       + CONFIG['file_type']
    return form_absolute_path_from_dir_and_file(org_workspace_dir, output_file_name)


def form_dir_to_store_org_repo(org_name):
    org_workspace_dir = get_org_workspace_path(org_name)
    repos_dir = os.path.join(org_workspace_dir, CONFIG['repos_path'])
    make_sure_dir_exist(repos_dir)
    return repos_dir


def assemble_cloc_command_for_repo(repo_name):
    cloc_tool_path = os.path.join(BASE_DIR, CONFIG['tool_path'], CONFIG['cloc_tool'])
    lang_def_path = os.path.join(BASE_DIR, CONFIG['tool_path'], CONFIG['lang_def_file'])
    cmd = [cloc_tool_path, '--read-lang-def=' + lang_def_path, '--by-file-by-lang', repo_name,
           '--file-encoding=utf-8']
    if CONFIG['cloc_file_no_scan']:
        cmd.append('--not-match-f=' + '(' + '|'.join(CONFIG['cloc_file_no_scan']) + ')')
    # cmd.append('--ignored=' + os.path.join(BASE_DIR, 'cloc_ignored_file.txt'))
    return cmd


def is_cloc_end_properly(last_line):
    last_line = last_line.strip()
    matched = re.match(r'(\d+ files? ignored.|-+)', last_line)
    return True if matched else False


def is_line_contains_blame_info(line):
    return '(<' in line


def is_line_contains_author_info(line):
    return 'Author' in line


def is_line_contains_contribution_info(line):
    matches = FILE_MOD_PATTERN_SHOW.match(line)
    return matches is not None


if __name__ == '__main__':
    pass
